#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <fcntl.h>

#include "head.h"

void init_list(struct shared_struct* head, int* count, int size){
    
    *count = 0;
    
    struct shared_struct* temp = head;

    int i;
    for(i = 0; i < size; ++ i){
        
        if(i == size - 1){
            temp->next = 0;
            return;
        }
        
        temp->next = temp + 1;
        temp = temp->next;
    }
}

int main(int argc, char *argv[])
{
    struct stat fileattr;
    key_t key; /* of type int */
    int shmid; /* shared memory ID */
    void *shmptr;
    struct shared_struct *shared; /* structured shm */
    pid_t childpid1, childpid2;
    char pathname[80], key_str[10], cmd_str[80];
    int shmsize, ret;

    shmsize = TEXT_NUM*sizeof(struct shared_struct) + 3 * sizeof(int)  ;
    printf("max record number = %d, shm size = %d\n", TEXT_NUM, shmsize);

    if(argc <2) {
        printf("Usage: ./a.out pathname\n");
        return EXIT_FAILURE;
    }
    strcpy(pathname, argv[1]);

    if(stat(pathname, &fileattr) == -1) {
        ret = creat(pathname, O_RDWR);
        if (ret == -1) {
            ERR_EXIT("creat()");
        }
        printf("shared file object created\n");
    }
 
    key = ftok(pathname, 0x27); /* 0x27 a project ID 0x0001 - 0xffff, 8 least bits used */
    if(key == -1) {
        ERR_EXIT("shmcon: ftok()");
    }
    printf("key generated: IPC key = %x\n", key); /* can set any nonzero key without ftok()*/

    shmid = shmget((key_t)key, shmsize, 0666|PERM);
    if(shmid == -1) {
        ERR_EXIT("shmcon: shmget()");
    }
    printf("shmcon: shmid = %d\n", shmid);

    shmptr = shmat(shmid, 0, 0); /* returns the virtual base address mapping to the shared memory, *shmaddr=0 decided by kernel */

    if(shmptr == (void *)-1) {
        ERR_EXIT("shmcon: shmat()");
    }
    printf("shmcon: shared Memory attached at %p\n", shmptr);
    
    int* lock = (int*)shmptr;
    int * count_ptr = (int *)(shmptr + 4);
    int* lock2 = (int*)(shmptr + 8);
    struct shared_struct* head = (struct shared_struct*)(shmptr + 12);

    *lock = 0;
    *lock2 = 1;

    init_list(head,count_ptr, TEXT_NUM);

    printf("\n");

    printList(head, TEXT_NUM);

    int i;
    for(i = 0; i < TEXT_NUM ; ++ i){

        char buf[20];
        sprintf(buf, "name%d", i);

        int id = rand() % 20;

        insert(head,count_ptr,TEXT_NUM, buf, id);
    }

    printf(" 13 is node %d\n",search(head,TEXT_NUM,13,0, head));

    printList(head,TEXT_NUM);

    sprintf(cmd_str, "ipcs -m | grep '%d'\n", shmid); 
    printf("\n------ Shared Memory Segments ------\n");
    system(cmd_str);
	
    if(shmdt(shmptr) == -1) {
        ERR_EXIT("shmcon: shmdt()");
    }

    printf("\n------ Shared Memory Segments ------\n");
    system(cmd_str);

    
    if (shmctl(shmid, IPC_RMID, 0) == -1) {
                ERR_EXIT("shmcon: shmctl(IPC_RMID)");
            }
    else {
        printf("shmcon: shmid = %d removed \n", shmid);
        printf("\n------ Shared Memory Segments ------\n");
        system(cmd_str);
        printf("nothing found ...\n"); 
    }

    exit(EXIT_SUCCESS);
}

